#ifndef _OLEDB_H_
#define _OLEDB_H_


#include <winsock2.h>
#include <utillib/memory/memory.h>
#include <databaselib/io/DataType.h>
#include <databaselib/io/Database.h>
#include <utillib/stl/QueueList.h>

#define	DBINITCONSTANTS
#define	INITGUID
#define	_UNICODEOLE32

#include <oledb.h>
#include <oledberr.h>

#define	TRY_DB_RECONNECTION					10
#define	SLEEP_TIME							10
#define	QUERY_LENGTH						4096
#define	VALUE_SIZE							1024
#define	MAX_FETCH_CLOUMN					1024
#define	MAX_FETCH_BUFFER					8192

#include <time.h>
#include <windows.h>
#include <utillib/util/synchronized.h>

#ifdef _DEBUG
#pragma comment ( lib, "DataBaseD.lib" )
#else
#pragma comment ( lib, "DataBase.lib" )
#endif


/*
	DBMS Contol By OLEDB Class
*/

#pragma comment ( lib, "ole32.lib" )
#pragma comment ( lib, "oleaut32.lib" )
#pragma comment ( lib, "uuid.lib" )

namespace databaselib
{
	namespace io
	{
		class AgentOLEDB;

		class OLEDB : public Database
		{
		public:
			OLEDB( AgentOLEDB *parentDB );
			virtual ~OLEDB();

			bool initializeDataBaseEnv( char *serverAddress , char *userid, char *password, char *catalog = NULL );
			bool releaseDataBaseEnv();

			virtual bool connect();
			virtual bool release( );

			virtual bool executeSQL(const char *query );
			virtual bool fetch();

			unsigned long getCountColumn();
			bool getColumnsInfo();

			int getInt( long out = -1 );
			__int64 getBigInt( long out = -1 );
			double getDouble( long col = -1 );

			char *getString( long col = -1 );

			bool getDateTime(struct tm &tm, long col = -1 );
			bool getDate( SmallDate &smallDate, long col = -1 );
			
			//	Overloading Operator */
			virtual OLEDB& operator >> ( char *out )
			{
				char *szResult = getString();
				if ( szResult != NULL ) strcpy_s( out, MAX_DB_STRING_SIZE, szResult );
				return ( *this );
			};
			virtual OLEDB& operator >> ( char &out )
			{
				out = ( char )getInt();
				return ( *this );
			};
			virtual OLEDB& operator >> ( bool &out )
			{
				out = false;
				if ( ( char )getInt() == 1 )  out = true;
				return ( *this );
			};

			virtual OLEDB& operator >> ( unsigned int &out )
			{
				out = ( unsigned int )getInt();
				return ( *this );
			};

			virtual OLEDB& operator >> ( int &out )
			{
				out = getInt();
				return ( *this );
			};

			virtual OLEDB& operator >> ( unsigned long &out )
			{
				out = ( unsigned long )getInt();
				return ( *this );
			};

			virtual OLEDB& operator >> ( __int64 &out )
			{
				out = getBigInt();
				return ( *this );
			};

			virtual OLEDB& operator >> ( float &out )
			{
				out = ( float )getDouble();
				return ( *this );
			};

			virtual OLEDB& operator >> ( short &out )
			{
				out = ( short )getInt();
				return ( *this );
			};

			virtual OLEDB& operator >> ( unsigned short &out )
			{
				out = ( unsigned short )getInt();
				return ( *this );
			};

			virtual OLEDB& operator >> ( struct tm &out )
			{
				getDateTime( out );
				return ( *this );
			};
			virtual OLEDB& operator >> ( SmallDate &out )
			{
				getDate( out );
				return ( *this );
			};
			virtual OLEDB& operator >> ( unsigned char &out )
			{
				out = ( unsigned char)getInt();
				return ( *this );
			};

		private:
			bool initialize();

			bool getDBSession( IDBCreateSession **createSession );

			HRESULT _executeSQL(const char *query);
			bool _fetch();
			bool endFetch();

			LPOLESTR m_oleQuery;

			unsigned  long m_columnPos;
			char *m_value;
			bool m_isExecute;

			char *m_buffer;
			unsigned long  m_colSize;

			long m_numRows;
			unsigned long m_numCols;

			IDBInitialize *m_IDBInitialize;
			ICommandText *m_ICommandText;
			IDBCreateSession *m_IDBCreateSession;
			IDBCreateCommand *m_IDBCreateCommand;
			IRowset *m_IRowset;
			ICommand *m_ICommand;
			IAccessor *m_IAccessor;
			HACCESSOR m_Accessor;

			DBCOLUMNINFO *m_DBColumnInfo;
			DBBINDING *m_Binding;

			HROW m_Row[1];
			HROW *m_RowPointer;

			AgentOLEDB *m_agentAgentDB;
			
		};


		class AgentOLEDB 	: public AgentDB /* DataBase(OLE DB) Control Class */
		{
		public:

			AgentOLEDB();
			virtual ~AgentOLEDB();

		public:
			virtual bool initializeDataBaseEnv( char *dataBaseIP, char *defaultDB, char *userid, char *password );
			virtual bool releaseDataBaseEnv();

			virtual Database *getNewDBInstance();

			bool getDBInitialize( IDBInitialize **DBInitialize );
			
		protected:

			LPOLESTR m_password;
			LPOLESTR m_userid;
			LPOLESTR m_serverAddress;
			LPOLESTR m_catalog;
		};
	}
}


#endif


